In computing systems, “observability” refers to the ability to obtain information about the internal workings of the software of the system as the system is operating. For example, observability allows a programmer or user to keep track of the values of variables, the number of times a function or module is called, the amount of time various computing tasks take to complete, etc. Observability code is therefore ancillary to the main code that actually performs the function of the software.
Although the inclusion of observability code incurs an overhead cost, the inclusion of observability may be particularly important or desirable in embedded systems. An embedded system is a computer system designed for specific functions and that is embedded as part of a complete device. Embedded computing systems are ubiquitous in modern society, and can include machine controllers, thermostats, engine controllers, watches, media players, etc. The embedded computing device on which computer program code is loaded is referred to herein as a “target platform” or more simply as a “target.”
Embedded systems may be contrasted with general-purpose computers, which are typically designed to be flexible and powerful, with a wide range of peripheral connectivity options. While general purpose computing systems typically include a wide range of input/output and storage capabilities, the I/O and storage capabilities of embedded systems may be more limited. Therefore, it may be difficult to monitor the activity and behavior of software in an embedded system without the assistance of observability code.
Functions and instructions which enable observability in software can be included in the source code of the software prior to compilation. (Compilation refers to the conversion of human-readable source code into machine readable instructions referred to as “machine code” or “object code.”) Compiling observability code into the machine code can undesirably increase the size of the machine code, however. Alternatively, machine instructions which cause an interrupt can be inserted into the program memory while the program is running on a target platform. However, it can be difficult to determine exactly wherein the program memory such instructions should be placed.
Conventional approaches to providing observability involve the compiler generation of debug information including the program memory location of lines of code and the memory locations (addresses or register names) of variables and data structures, coupled with a debugging program running on a host computer that can interact very closely with the target program. However, with those approaches, there is no notion of particularly interesting observability points—all locations in the code are treated as equally interesting. Locations in the code, and locations of interesting data structures can become obfuscated by the compiler's machine code optimization. The actual insertion of observability instructions at such locations can be problematic (finding the appropriate location) and inefficient (often involve interrupts). These methods can also interfere with proper operation of the target, and may require a skilled user with in-depth knowledge of the source code. Often, for a deployed target, there is no host computer that has the appropriate connection to the target to even attempt to perform this type of debugging.